﻿using BattleBotsMattAndSunny.Components.Interfaces;
using BattleBotsMattAndSunny.Utilities;
using Robocode;
using Robocode.Util;
using System;

namespace BattleBotsMattAndSunny.Components.Guns
{
    public class CircularGunner : IGunManager
    {
        private AdvancedRobot robot { get; set; }

        private IDataManager dataManager { get; set; }

        public CircularGunner(IDataManager dm, AdvancedRobot r)
        {
            dataManager = dm;
            robot = r;
        }

        public void OnScannedRobot(ScannedRobotEvent e, double power)
        {
            var enemy = dataManager.GetEnemy(e.Name);
            power = Math.Min(power, robot.Energy); //shoot till its gone

            double t = 0;

            var predictedX = enemy.X;
            var predictedY = enemy.Y;
            while ((++t) * (20.0 - 3.0 * power) <
                  RoboMath.GetDistance(robot.X, robot.Y, predictedX, predictedY))
            {
                predictedX += Math.Sin(enemy.HeadingRadians) * enemy.Velocity;
                predictedY += Math.Cos(enemy.HeadingRadians) * enemy.Velocity;
                enemy.HeadingRadians += enemy.HeadingChange.GetValueOrDefault();
                if (predictedX < 18.0
                    || predictedY < 18.0
                    || predictedX > robot.BattleFieldWidth - 18.0
                    || predictedY > robot.BattleFieldHeight - 18.0)
                {
                    predictedX = Math.Min(Math.Max(18.0, predictedX),
                        robot.BattleFieldWidth - 18.0);
                    predictedY = Math.Min(Math.Max(18.0, predictedY),
                        robot.BattleFieldHeight - 18.0);
                    break;
                }
            }
            var angle = Utils.NormalAbsoluteAngle(Math.Atan2(
                predictedX - robot.X, predictedY - robot.Y));

            robot.SetTurnGunRightRadians(Utils.NormalRelativeAngle(
                angle - robot.GunHeadingRadians));
            Fire(power);
        }

        public void Fire(double power)
        {
            //Fire and store the bullet todo move this to abstract GunManager class
            dataManager.StoreBullet(robot.SetFireBullet(power));
        }

        public void Move()
        {
        }
    }
}